Add configurable UUID conversion for non-AWS SQS-compatible services#1433
Add configurable UUID conversion for non-AWS SQS-compatible services#1433jm0514 wants to merge 13 commits intoawspring:mainfrom
Conversation
| accessor.setHeader(SqsHeaders.SQS_AWS_MESSAGE_ID_HEADER, source.messageId()); | ||
| MessageHeaders messageHeaders = accessor.toMessageHeaders(); | ||
| logger.trace("Mapped headers {} for message {}", messageHeaders, source.messageId()); | ||
| return new MessagingMessageHeaders(messageHeaders, UUID.randomUUID()); |
There was a problem hiding this comment.
Passing a random UUID does not feel right. Perhaps MessagingMessageHeaders can have id set as String instead of UUID? cc @tomazfernandes
There was a problem hiding this comment.
Thanks for the suggestion! Updated to generate UUID from Message ID instead of random UUID.
|
Hey @jm0514, thanks for the PR!
@maciejwalkowiak, the issue there is that the Might be worth raising with the Spring Messaging team? In the meantime, I think we can make the solution simpler if we leverage the fact that most ID-related operations are made through the Instead of requiring a configuration change to support other ID types, we could simplify the logic by trying to parse the UUID, and if it fails we add the new header as suggested in the PR. Then in the The caveat would be that for non UUID ids, the result from getting the ID header directly would be a random UUID, but I don't think there's a way around it with the existing What do you folks think? |
|
tomazfernandes
left a comment
There was a problem hiding this comment.
Hey @jm0514, thanks for the updates. Overall direction looks solid.
I have a couple of suggestions to simplify the design and reduce duplication.
| public MessagingMessageConverter<Message> messageConverter(ObjectProvider<JsonMapper> jsonMapperProvider) { | ||
| JsonMapper jsonMapper = jsonMapperProvider.getIfAvailable(); | ||
| return jsonMapper != null ? new SqsMessagingMessageConverter(jsonMapper) | ||
| public MessagingMessageConverter<Message> messageConverter(ObjectProvider<JsonMapper> jsonMapperProvider, |
There was a problem hiding this comment.
Currently the auto-config manually creates a SqsHeaderMapper and sets the flag on it. Instead, let's add convertMessageIdToUuid as a property on both SqsContainerOptions and SqsTemplateOptions, so auto-config just does:
factory.configure(options -> options.convertMessageIdToUuid(sqsProperties.getConvertMessageIdToUuid()));
builder.configure(options -> options.convertMessageIdToUuid(sqsProperties.getConvertMessageIdToUuid()));
This keeps the configuration surface consistent between container and template, removes the manual SqsHeaderMapper creation from auto-config, and gives programmatic users (without auto-config) a clean way to set it through the standard options API.
There was a problem hiding this comment.
Thanks for the great suggestion! This makes the configuration much cleaner and consistent with the existing patterns.
Applied in 1d32b0c. Moved convertMessageIdToUuid to both SqsContainerOptions and SqsTemplateOptions, so auto-config now uses factory.configure() and builder.configure() instead of manually creating SqsHeaderMapper.
Added getHeaderMapper() to AbstractMessagingMessageConverter to propagate the option to the header mapper.
spring-cloud-aws-sqs/src/main/java/io/awspring/cloud/sqs/support/converter/SqsHeaderMapper.java
Show resolved
Hide resolved
There was a problem hiding this comment.
@jm0514, thanks for the updates. I left a few comments, we're getting closer.
The main point is that there's a mismatch between what Spring Messaging exposes, which is a UUID-based Message, and the SQS contract, which uses String ids.
Therefore we need a consistent message-id translation layer exposed consistently to users regardless of whether they're using SQS directly or another compatible implementation.
This also makes it easier to move between SQS and SQS-compatible services over time.
Also, please add @since 4.1.0 to the new classes.
spring-cloud-aws-sqs/src/main/java/io/awspring/cloud/sqs/operations/SqsTemplate.java
Outdated
Show resolved
Hide resolved
spring-cloud-aws-sqs/src/main/java/io/awspring/cloud/sqs/operations/SqsTemplateParameters.java
Outdated
Show resolved
Hide resolved
spring-cloud-aws-sqs/src/main/java/io/awspring/cloud/sqs/operations/SqsTemplate.java
Outdated
Show resolved
Hide resolved
...src/main/java/io/awspring/cloud/sqs/support/converter/AbstractMessagingMessageConverter.java
Outdated
Show resolved
Hide resolved
...ud-aws-sqs/src/main/java/io/awspring/cloud/sqs/listener/source/AbstractSqsMessageSource.java
Outdated
Show resolved
Hide resolved
spring-cloud-aws-sqs/src/main/java/io/awspring/cloud/sqs/operations/SqsTemplateOptions.java
Show resolved
Hide resolved
tomazfernandes
left a comment
There was a problem hiding this comment.
@jm0514 thanks for the changes. looks great!
I've left a couple of small comments.
Please also update:
- The
AbstractListenerObservationclass to use thegetRawMessageIdmethod, so observability tags reflect the broker id when it's non-UUID. - The doc to reflect that the new header is added both with the flag on and off.
Thanks.
| MessageHeaders withRawId = MessageHeaderUtils.addHeaderIfAbsent(headers, SqsHeaders.SQS_RAW_MESSAGE_ID_HEADER, | ||
| messageId); | ||
| if (isValidUuid(messageId)) { | ||
| return new MessagingMessageHeaders(withRawId, UUID.fromString(messageId)); |
There was a problem hiding this comment.
Not critical, but we're converting UUID.fromString twice.
Perhaps the isValidUuid method could return an Optional<UUID> so we convert it only once. Method name might need to be adjusted as well.
| Map<String, Object> additionalInfo = new HashMap<>(); | ||
| if (sequenceNumber != null) { | ||
| additionalInfo.put(SqsTemplateParameters.SEQUENCE_NUMBER_PARAMETER_NAME, sequenceNumber); | ||
| } |
There was a problem hiding this comment.
Looks good, but we're returning the original message which does not contain the new header.
|
@tomazfernandes Thanks for catching these — I missed the header propagation issue in SendResult while refactoring. Here's a summary of the changes:
|
Add configurable UUID conversion for non-AWS SQS-compatible services
📢 Type of change
📜 Description
Added configurable support for SQS-compatible cloud services (like Yandex Message Queue) that use non-UUID MessageId formats. The framework now supports both UUID and non-UUID MessageId handling through a new configuration option.
Configuration:
💡 Motivation and Context
Solves #814
💚 How did you test it?
SqsHeaderMapperandMessageHeaderUtils📝 Checklist
🔮 Next steps